package com.cjm.one.strategy;

import com.cjm.one.model.coupon.entity.CouponInfo;
import com.cjm.one.model.coupon.vo.CouponInfoVo;
import com.cjm.one.model.goods.entity.GoodsSku;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class CouponPool {
    private final Map<Long, CouponInfoVo> available = new HashMap<>();
    private final Set<Long> usedCoupons = new HashSet<>();



    public List<CouponInfoVo> getApplicableCoupons(GoodsSku sku) {
        log.info("所有优惠卷：{}",available.values());
        return available.values().stream()
                .filter(c -> !usedCoupons.contains(c.getId()))
                .filter(c -> isApplicableForSku(c, sku))
                .collect(Collectors.toList());
    }

    public synchronized void markUsed(Long couponId) {
        usedCoupons.add(couponId);
        available.remove(couponId);
    }

    private boolean isApplicableForSku(CouponInfoVo coupon, GoodsSku sku) {
        // 复用原有isCouponApplicable逻辑
        switch (coupon.getRangeType()) {
            case 3: return matchesSku(coupon, sku);
            case 2: return matchesCategory(coupon, sku);
            case 1: return true;
            default: return false;
        }
    }

    public boolean matchesSku(CouponInfoVo coupon, GoodsSku sku) {
        return coupon.getRangeList().stream()
                .anyMatch(r -> r.getRangeId().equals(sku.getGoodsId()));
    }
    public boolean matchesCategory(CouponInfoVo coupon, GoodsSku sku) {
        return coupon.getRangeList().stream()
                .anyMatch(r ->
                        r.getRangeId().equals(sku.getCategory1Id()) ||
                                r.getRangeId().equals(sku.getCategory2Id()));
    }
    
    public CouponPool(List<CouponInfoVo> coupons) {
        coupons.forEach(c -> available.put(c.getId(), c));
    }
    
    public boolean hasRemaining() {
        return !available.isEmpty();
    }
    
    public CouponInfoVo findBestForSku(BigDecimal price) {
        return available.values().stream()
            .filter(c -> meetsCondition(price, c))
            .max(Comparator.comparing(CouponInfoVo::getAmount))
            .orElse(null);
    }
    

    
    private boolean meetsCondition(BigDecimal price, CouponInfoVo coupon) {
        return price.compareTo(coupon.getConditionAmount()) >= 0;
    }
}